#pragma once
#ifndef _Include_ChessPiece_h_
#define _Include_ChessPiece_h_

#include "stdafx.h"
#include "ChessBoard.h"

class ChessPiece
{
public:
    ChessPiece() { m_chess_pos.row_index = INVALID_INDEX; m_chess_pos.col_index = INVALID_INDEX; }
    ChessPiece(int row_index, int col_index)
    {
        m_chess_pos.row_index = row_index;
        m_chess_pos.col_index = col_index;
    }
    virtual ~ChessPiece() {}

public:
    virtual HRESULT MoveCheck(const CHESS_POS& m_select_pos) = 0;
    virtual HRESULT DrawCanMove(const HWND& hwnd) = 0;

public:
    virtual HRESULT SetChessBoard(const std::shared_ptr<ChessBoard>& chess_board)
    {
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_NULL(m_chess_board = chess_board)

        return S_OK;
    }

    virtual HRESULT SetChessPos(CHESS_POS chess_pos)
    {
        m_chess_pos = chess_pos;

        return S_OK;
    }

    virtual HRESULT GetChessPos(CHESS_POS& chess_pos) const
    {
        chess_pos = m_chess_pos;

        return S_OK;
    }

    virtual HRESULT GetRectPos(RECT& rect) const
    {
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_NULL(m_chess_board.get())
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FAILED(
            m_chess_board.get()->GetRectByChessPos(m_chess_pos, rect))

        return S_OK;
    }

    virtual HRESULT SetChessType(CHESS_TYPE chess_type)
    {
        m_chess_type = chess_type;

        return S_OK;
    }

    virtual HRESULT GetChessType(CHESS_TYPE& chess_type) const
    {
        chess_type = m_chess_type;

        return S_OK;
    }

    virtual HRESULT SetTypeName(int type_name)
    {
        m_type_name = type_name;

        return S_OK;
    }

    virtual HRESULT SetSelect(BOOL select)
    {
        m_is_select = select;

        return S_OK;
    }

    virtual HRESULT IsSelect(BOOL& is_select)
    {
        is_select = m_is_select;

        return S_OK;
    }

    virtual HRESULT DrawSelected(const HWND& hwnd)
    {
        HDC hdc = GetDC(hwnd);

        HPEN select_pen = CreatePen(PS_SOLID, 1, RGB(0x0, 0xFF, 0x0));
        SelectObject(hdc, select_pen);
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FAILED(DrawRectangle(hdc, m_chess_pos))

        return S_OK;
    }

    virtual HRESULT GetChessCanMove(std::vector<CHESS_POS>& chess_move)
    {
        chess_move = m_can_move;

        return S_OK;
    }

protected:
    HRESULT DrawRectangle(const HDC& hdc, const CHESS_POS& m_select_pos)
    {
        POINT left_top;
        left_top.x = GC_CHESS_PIECE_WIDTH * m_select_pos.col_index + 1;
        left_top.y = GC_CHESS_PIECE_HEIGHT * m_select_pos.row_index + 1;
        POINT right_top;
        right_top.x = GC_CHESS_PIECE_WIDTH * (m_select_pos.col_index + 1) - 1;
        right_top.y = left_top.y;
        POINT left_bottom;
        left_bottom.x = left_top.x;
        left_bottom.y = GC_CHESS_PIECE_HEIGHT * (m_select_pos.row_index + 1) - 1;
        POINT right_bottom;
        right_bottom.x = right_top.x;
        right_bottom.y = left_bottom.y;
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FAILED(DrawLine(hdc, left_top, right_top))
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FAILED(DrawLine(hdc, right_top, right_bottom))
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FAILED(DrawLine(hdc, right_bottom, left_bottom))
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FAILED(DrawLine(hdc, left_bottom, left_top))

        return S_OK;
    }

    HRESULT DrawLine(const HDC& hdc, const POINT& start_point, const POINT& end_point)
    {
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FALSE(MoveToEx(hdc, start_point.x, start_point.y, NULL))
        RETURN_AND_RECORD_ERROR_MESSAGE_IF_FALSE(LineTo(hdc, end_point.x, end_point.y))

        return S_OK;
    }

protected:
    CHESS_POS m_chess_pos;
    std::vector<CHESS_POS> m_can_move;
    BOOL m_is_select;
    int m_type_name;
    CHESS_TYPE m_chess_type;
    std::shared_ptr<ChessBoard> m_chess_board;
};

#endif//_Include_ChessPiece_h_